iOS开发多线程知识梳理

您所在的位置:网站首页 ios 线程锁面试 iOS开发多线程知识梳理

iOS开发多线程知识梳理

2024-04-24 17:54| 来源: 网络整理| 查看: 265

线程和进程

几乎所有的操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个程序就是一个进程。当一个程序运行时,内部可能包含了多个顺序执行流,每个顺序执行流就是一个线程。

进程(Process )

当一个程序进入内存运行后,即变成一个进程。进程是处于是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位。一般而言,进程有如下特征:

独立性:有自己独立的资源,且拥有自己私有的地址空间。在没有经过进程本省的允许下,其他进程是不能直接访问其进程的地址空间的。 动态性:程序只是静态的指令集合,而进程是一个正在系统中活动的指令集合。进程有时间的概念,具有自己的生命周期和各种状态。 并发性:多个进程可以在单个处理器上并发执行,互相不会影响。 线程(Thread)

线程也被称做轻量级进程,线程是进程的执行单元。就像进程在系统中一样,线程在进程中也是独立的,并发的执行流程。一个进程可以拥有多个线程,一个线程必须有一个父进程,但不再拥有系统资源,而是和父进程一起共享父进程的全部资源。多线程由于共享父进程的资源,所以编程更加方便,但是也需要小心线程不会影响到父进程中的其他线程。线程是独立运行的,它并不知道其他线程的存在。线程执行是抢占式的,也就是说,当前运行的线程在任何时候都可能被挂起,以便林另外一个线程可以运行。

多线程优点 进程间不可以共享内存,但线程之间共享内存十分容易。 系统创建进程需要为其重新分配系统资源,但是创建线程代价小得多,因此效率更高 为什么要用多线程编程

为了提高资源利用率来提升系统整体效率,实际往往是将耗时操作放在后台执行,避免阻塞主线程,在iOS中UI绘制和用户响应都是主线程。

NSThread

常用API

- (void)viewDidLoad { [super viewDidLoad]; //打印当前线程 NSLog(@"开始:%@ 优先级:%d", [NSThread currentThread], [NSThread currentThread].qualityOfService); //1.创建NSTread对象,必须调用start方法开始,并且只能传一个参数object NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"test"]; // NSThread *thread = [[NSThread alloc] initWithBlock:^{}]; thread.name = @"testThread"; thread.qualityOfService = NSQualityOfServiceUserInteractive; [thread start]; //2.直接创建并启动线程 // [NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"test"]; // [NSThread detachNewThreadWithBlock:^{}]; //3.隐式直接创建 // [NSThread performSelectorInBackground:@selector(run:) withObject:nil]; // NSLog(@"结束:%@", [NSThread currentThread]); } - (void)run:(NSObject *)object { //阻塞休眠 // [NSThread sleepForTimeInterval:5]; //中止当前线程 // [NSThread exit]; NSLog(@"子线程运行:%@ %@ 优先级:%d", [NSThread currentThread], object, [NSThread currentThread].qualityOfService); } 线程的状态

线程被启动后,并不是直接进入执行状态,也不是一直处于执行状态,由于线程并发,线程会反复在运行、就绪间切换。创建一个线程后,处于新建状态,系统为其分配内存,初始化成员变量;调用-(void)start;方法后,该线程处于就绪状态,系统为其创建方法调用栈和程序计数器,此时并没有运行,何时运行取决于系统调度。

终止子线程

每个线程都有一定的优先级,优先级越高获得执行机会越多。目前通过qualityOfService属性来设置,原来的threadPriority由于语义不够清晰,已经被废弃了。

NSQualityOfServiceUserInteractive:最高优先级,主要用于提供交互UI的操作,比如处理点击事件,绘制图像到屏幕上 NSQualityOfServiceUserInitiated:次高优先级,主要用于执行需要立即返回的任务 NSQualityOfServiceDefault:默认优先级,当没有设置优先级的时候,线程默认优先级 NSQualityOfServiceUtility:普通优先级,主要用于不需要立即返回的任务 NSQualityOfServiceBackground:后台优先级,用于完全不紧急的任务 缺点

使用NSThread进行多线程编程较复杂,需要自己控制多线程的同步、并发,还需要自己控制线程的终止销毁,稍有不留神容易出现错误,对开发者要求较高,一般较少使用。

NSOperation

iOS还提供了NSOperation与NSOperationQueue来实现多线程,是基于GCD更高一层的封装,完全面向对象。但是GCD更简单易用、代码可读性也更高。

NSOperationQueue:负责管理系统提交的多个NSOperation,底层维护了一个线程池。不同于GCD中的调度队列FIFO(先进先出)原则。NSOperationQueue对于添加到队列中的操作,首先进入准备就绪的状态(就绪状态取决于操作之间的依赖关系),然后进入就绪状态的操作的开始执行顺序(非结束执行顺序)由操作之间相对的优先级决定(优先级是操作对象自身的属性)。

NSOperation: 代表一个多线程任务。

为什么要使用NSOperation、NSOPerationQueue? 可以添加完成的代码块,在操作完成后执行。 添加操作之间的依赖关系,方便的控制执行顺序。 设定操作执行的优先级。 可以很方便的取消一个操作的执行。 使用KVO观察对操作执行状态的更改:isExecuteing、isFinished、isCancelled。 常用API NSOperationQueue *queue; //获取执行当前NSOperation的NSOperationQueue队列 // queue = [NSOperationQueue currentQueue]; //获取主线程的NSOperationQueue队列 // queue = [NSOperationQueue mainQueue]; //自定义队列 queue = [[NSOperationQueue alloc] init]; //队列名 queue.name = @"testOperationQueue"; //最大并发操作数(系统有限制,即使设置很大,也会自动调整) queue.maxConcurrentOperationCount = 10; //设置优先级 queue.qualityOfService = NSQualityOfServiceDefault; //自定义NSOperation,如果SEL和Block为空,系统不会加入到指定队列 NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil]; NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOperation"); }]; //添加依赖关系,invocationOperation执行完后才执行blockOperation [blockOperation addDependency:invocationOperation]; //添加到队列中 // [queue addOperation:invocationOperation]; [queue addOperations:@[invocationOperation, blockOperation] waitUntilFinished:NO]; //直接添加代码块任务 [queue addOperationWithBlock:^{ }]; //打印所有的NSOperation for(int i=0; i0, 就减1,然后往下执行后面的代码 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //让信号量的值加1 dispatch_semaphore_signal(semaphore);

8. dispatch_queue

直接使用GCD的串行队列,也是可以实现线程同步的 dispatch_queue_t queue = dispatch_queue_creat("lock_queue", DISPATCH_QUEUE_SERIAL); dispatch_sync(queue, ^{ //任务 })


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3